/*
 Copyright 2008 Under Dusken

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

package org.dyndns.anderlin.jmplayer.dao;

import org.springframework.dao.DataAccessException;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * A generic interface to Data Access Objects using Java 5.0 Generics.
 *
 *
 * @author Erlend Hamnaberg<erlenha@underdusken.no>
 */
public interface GenericDao {

    /**
     * Gets an object from the database, or throws a DataAccessException if not
     * found.
     *
     * @param ID can be of any serializable class.
     * @return an object of specified type.
     * @throws DataAccessException
     */
    <T, PK extends Serializable> T getByID(Class<T> type, PK ID) throws DataAccessException;

    /**
     * Gets a proxyreference to the object.. Does not hit the database. Useful
     * for getting objects in controllers.
     *
     * @param ID
     * @return
     * @throws DataAccessException
     */
    <T, PK extends Serializable> T getReference(Class<T> type, PK ID) throws DataAccessException;

    /**
     * Gets a list of objects of the specified type based on a Query. This might
     * for instance be a HQL, SQL or EJB-QL query. If you choose not to
     * implement this, do one of two things. Either let it throw a
     * NotImplementedException. Or always return null. The latter is
     * recommended.
     *
     * @param query the query to query by
     * @param map   a map of named parameters.
     * @return
     * @throws DataAccessException
     */
    <T> List<T> getByQuery(String query, Map<String, ?> map)
            throws DataAccessException;

    /**
     * @param query
     * @param map
     * @param offset
     * @param size
     * @return
     * @throws DataAccessException
     * @see #getByQuery(String,java.util.Map<java.lang.String,? extends
     *      java.lang.Object>) This also adds pagination.
     */
    <T> List<T> getByQuery(String query, Map<String, ?> map,
                       int offset, int size) throws DataAccessException;

    /**
     * @param query the named query to query by.
     * @param map   named parameters
     * @return
     * @throws DataAccessException
     * @see #getByQuery(String,java.util.Map<java.lang.String,? extends
     *      java.lang.Object>) This however, is a named query. example: <code>
     *      articleDao.getByNamedQuery("articles_all",null);
     *      </code>
     */
    <T> List<T> getByNamedQuery(String query, Map<String, ?> map)
            throws DataAccessException;

    Integer getNumberByNamedQuery(String query, Map<String, ?> map)
            throws DataAccessException;

    /**
     * @param query  the named query
     * @param map    named parameters
     * @param offset what page are we on?
     * @param size   show this many on the page.
     * @return
     * @throws DataAccessException
     * @see #getByNamedQuery(String,java.util.Map<java.lang.String,? extends
     *      java.lang.Object>) This adds pagination.
     */
    <T> List<T> getByNamedQuery(String query, Map<String, ?> map,
                            int offset, int size) throws DataAccessException;

    /**
     * This can have different usages. If you want to delete the object from the
     * database, this can be used. However sometimes you dont want to delete
     * things. This can then have functionality to set the status to deleted,
     * then resave the object.
     *
     * @param object the object to remove/disable
     * @throws DataAccessException
     */
    <T> void remove(T object) throws DataAccessException;

    /**
     * Saves or update a persistent object to the storage facility.
     *
     * @param object the object to persist/merge.
     * @throws DataAccessException
     */
    <T> T saveOrUpdate(T object) throws DataAccessException;
}
